iT邦幫忙

2024 iThome 鐵人賽

DAY 29
0
Modern Web

雙向奔赴的websocket與冰冷的react系列 第 29

[day29]websocket與React : 獲取外部資料渲染

  • 分享至 

  • xImage
  •  

在這篇文章中,我們將展示如何使用 Node.js 來連接外部 API(如 CoinGecko 的比特幣價格 API),並通過 WebSocket 將比特幣的實時價格推送到 React 前端進行渲染。這是一個典型的前後端交互實戰案例,通過 WebSocket 的特性,可以實現比傳統 HTTP 請求更加流暢的數據更新效果。

  • 背景
    使用傳統的 HTTP 請求模式,每次前端需要數據時,必須手動觸發請求,而 WebSocket 則可以讓服務器主動將數據推送給前端。這使得 WebSocket 特別適合於像金融數據監控這樣需要頻繁更新的場景。

  • 項目需求
    1.後端通過 CoinGecko API 獲取比特幣的實時價格。
    2.後端使用 WebSocket 向前端定期推送比特幣價格。
    3.前端通過 WebSocket 接收價格並即時渲染。

server.js

記得安裝npm install ws axios

const WebSocket = require("ws");
const axios = require("axios"); // 用來請求 CoinGecko API 的庫
const wss = new WebSocket.Server({ port: 8080 });

// 每隔 10 秒從 CoinGecko API 獲取比特幣價格
const fetchBitcoinPrice = async () => {
    try {
        const response = await axios.get("https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd");
        return response.data.bitcoin.usd;
    } catch (error) {
        console.error("無法獲取比特幣價格", error);
        return null;
    }
};

// 當有客戶端連接時觸發
wss.on("connection", (ws) => {
    console.log("客戶端已連接");

    // 每隔 10 秒向所有連接的客戶端推送比特幣價格
    const intervalId = setInterval(async () => {
        const price = await fetchBitcoinPrice();
        if (price) {
            const message = JSON.stringify({
                type: "bitcoinPriceUpdate",
                price: price,
            });

            // 向所有已連接的客戶端推送價格更新
            wss.clients.forEach((client) => {
                if (client.readyState === WebSocket.OPEN) {
                    client.send(message);
                }
            });
        }
    }, 10000); // 每 10 秒更新一次價格

    ws.on("close", () => {
        console.log("客戶端已斷開連接");
        clearInterval(intervalId); // 清除定時器
    });
});

console.log("WebSocket 服務器運行在 ws://localhost:8080");

App.jsx

import React, { useState, useEffect, useRef } from 'react';

function App() {
  const [bitcoinPrice, setBitcoinPrice] = useState(null); // 儲存比特幣價格
  const ws = useRef(null);

  useEffect(() => {
    // 使用 WebSocket 連接到比特幣價格數據 API
    ws.current = new WebSocket('ws://localhost:8080'); // 替換為你後端 WebSocket 的地址

    ws.current.onopen = () => {
      console.log('WebSocket 連接成功');
    };

    // 當收到服務器的比特幣價格更新時
    ws.current.onmessage = (event) => {
      const data = JSON.parse(event.data);
      if (data.type === 'bitcoinPriceUpdate') {
        setBitcoinPrice(data.price); // 更新比特幣價格
      }
    };

    ws.current.onclose = () => {
      console.log('WebSocket 連接關閉');
    };

    ws.current.onerror = (error) => {
      console.error('WebSocket 錯誤:', error);
    };

    return () => {
      if (ws.current) {
        ws.current.close();
      }
    };
  }, []);

  return (
    <div style={{ textAlign: 'center', marginTop: '50px' }}>
      <h1>比特幣實時價格監控</h1>
      <h2>當前比特幣價格:{bitcoinPrice ? `$${bitcoinPrice}` : '加載中...'}</h2>
    </div>
  );
}

export default App;

結論

這樣,我們成功建立了一個簡單的比特幣價格監控應用。透過 Node.js 後端連接外部 API,並使用 WebSocket 即時推送數據給 React 前端,使得數據可以即時更新在頁面上。

但這種方式有明顯的缺點,例如為什麼設定更新間隔為 10 秒?這會導致數據更新變慢。原因在於頻繁的 API 請求會被阻擋,因為我們的資料是從外部 API 獲取的,這些 API 通常都有請求次數的限制。如果你使用爬蟲技術,或許可以更靈活,但也需要考慮爬蟲的合法性和技術挑戰。

這次練習的重點是讓你的服務端能夠接受外部數據,並將其通過 WebSocket 推送給前端,實現實時渲染。

原本想說架wss自簽,順便練習,結果架起來之後因為自簽的一些原因,瀏覽器或其他設備還是會有不安全,就沒說了,好了大概就這樣結束囉,感謝


上一篇
[day28]WebSocket 與 React 使用者對話
下一篇
[day30]結語
系列文
雙向奔赴的websocket與冰冷的react30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言